/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/
#include "ak_types.h"
#include "ak_lock.h"

/* In order to Support ASN.1 OP, -> 256K Buf */ 
#define 	STRACE_BUF_MAX 	0X40000

static 	FILE *			_gSTrace_File = NULL; 
static 	int 			_gSTrace_Switch = 0;
static 	_t_sysCS 		_gSTrace_Lock;


void 		STrace_Switch(int flag)
{
	if(flag == 0){
		_gSTrace_Switch = 0;	
	}
	else{
		_gSTrace_Switch = 1;
	}
	return;
}

	
/* Linux */
#if 	_TARGET_OS == _OS_GNU
void 		STrace_Printf(const char * funcN, int lineNo, char * pucFormat, ...)
{
	char			buffer[STRACE_BUF_MAX+1];
	va_list 		va;
	struct timeval	tv;
	struct tm	   *tm;

	if(pucFormat){
		if(_gSTrace_File == NULL){
			_gSTrace_File = fopen("trace.dat", "a");
			SYS_INIT_CS(&_gSTrace_Lock);
		}

		
		va_start(va, pucFormat);
		SYS_VSNPRINTF(buffer, STRACE_BUF_MAX, pucFormat, va);
		va_end(va); 

		gettimeofday(&tv, NULL);
		tm = localtime(&(tv.tv_sec));
		
		SYS_ENTER_CS(&_gSTrace_Lock);
		if(_gSTrace_Switch == 0){
			SYS_PRINTF("[%02d:%02d:%02d:%03d:%03d][%-20s][%04d:] %s",
				(int)(tm->tm_hour),	
				(int)(tm->tm_min), 	
				(int)(tm->tm_sec), 	
				(int)(tv.tv_usec/1000), 
				(int)(tv.tv_usec%1000),
				funcN, lineNo, buffer);
		}
		else{
			SYS_FPRINTF(_gSTrace_File,
				"[%02d:%02d:%02d:%03d:%03d][%-20s][%4d:] %s",
				(int)(tm->tm_hour),	
				(int)(tm->tm_min), 	
				(int)(tm->tm_sec), 	
				(int)(tv.tv_usec/1000), 
				(int)(tv.tv_usec%1000),
				funcN, lineNo, buffer);
			SYS_FFLUSH(_gSTrace_File);
		}
		SYS_LEAVE_CS(&_gSTrace_Lock);
	}		
	return;
}

void 		STrace_PrintfEx(char * pucFormat, ...)
{
	char			buffer[STRACE_BUF_MAX+1];
	va_list 		va;

	if(pucFormat){

		va_start(va, pucFormat);
		SYS_VSNPRINTF(buffer, STRACE_BUF_MAX, pucFormat, va);
		va_end(va); 

		SYS_ENTER_CS(&_gSTrace_Lock);
		if(_gSTrace_Switch == 0){
			SYS_PRINTF("%s", buffer);
		}
		else{
			SYS_FPRINTF(_gSTrace_File, "%s", buffer);
			SYS_FFLUSH(_gSTrace_File);
		}
		SYS_LEAVE_CS(&_gSTrace_Lock);
	}		
	return;
}

/* Windows */
#elif 	_TARGET_OS == _OS_WIN
void 		STrace_Printf(const char * funcN, int lineNo, char * pucFormat, ...)
{
	char			buffer[STRACE_BUF_MAX+1];
	va_list 		va;
	SYSTEMTIME  	tv;

	if(pucFormat){
		if(_gSTrace_File == NULL){
			_gSTrace_File = fopen("trace.dat", "a");
			SYS_INIT_CS(&_gSTrace_Lock);
		}
		if(_gSTrace_File){

			va_start(va, pucFormat);
			SYS_VSNPRINTF(buffer, STRACE_BUF_MAX, pucFormat, va);
			va_end(va); 
			GetSystemTime(&tv);
			
			SYS_ENTER_CS(&_gSTrace_Lock);
			/* Let's Trace & Flush */
			SYS_FPRINTF(_gSTrace_File, "[%-3d:%-3d:%-3d][%-20s][%-4d:] %s",
				tv.wMinute, tv.wSecond, tv.wMilliseconds, 
				funcN, lineNo, buffer);
			SYS_FFLUSH(_gSTrace_File);
			
			SYS_LEAVE_CS(&_gSTrace_Lock);
		}
	}		
	return;
}

void 		STrace_PrintfEx(char * pucFormat, ...)
{
	char			buffer[STRACE_BUF_MAX+1];
	va_list 		va;

	if(pucFormat){
		if(_gSTrace_File == NULL){
			_gSTrace_File = fopen("trace.dat", "a");
			SYS_INIT_CS(&_gSTrace_Lock);
		}
		if(_gSTrace_File){

			va_start(va, pucFormat);
			SYS_VSNPRINTF(buffer, STRACE_BUF_MAX, pucFormat, va);
			va_end(va); 

			SYS_ENTER_CS(&_gSTrace_Lock);
			/* Let's Trace & Flush */
			SYS_FPRINTF(_gSTrace_File, "%s", buffer);
			SYS_FFLUSH(_gSTrace_File);
			SYS_LEAVE_CS(&_gSTrace_Lock);
		}
	}		
	return;
}

#endif



static 	unsigned char _gSHexCharTbl[256]={
/* 0X00 - 0X0F */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0X10 - 0X1F */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0X20 - 0X2F */
' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',

/* 0X30 - 0X3F */
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',

/* 0X40 - 0X4F */
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',

/* 0X50 - 0X5F */
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', 

/* 0X60 - 0X6F */
'~', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',

/* 0X70 - 0X7F */
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '.',

/* 0X80 - 0X8F */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0X90 - 0X9F */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0XA0 - 0XAF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0XB0 - 0XBF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0XC0 - 0XCF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0XD0 - 0XDF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',

/* 0XE0 - 0XEF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',


/* 0XF0 - 0XFF */
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'

};


#define _STRACE_DUMP_DELIM 	16
void 		STrace_HexDump(unsigned char * pBuf, unsigned int lBuf)
{
	unsigned int 	i, j, k;
	unsigned char 	iCh;
	
	if(pBuf && (lBuf > 0)){
		k = 0;
		j = lBuf / _STRACE_DUMP_DELIM;
		for(i=0; i<j; i++){
			for(k=0; k<_STRACE_DUMP_DELIM; k++){
				iCh = *(pBuf + (i * _STRACE_DUMP_DELIM) + k);
				printf("%02x ",  iCh);
			}
			printf("\t");
			for(k=0; k<_STRACE_DUMP_DELIM; k++){
				iCh = *(pBuf + (i * _STRACE_DUMP_DELIM) + k);
				printf("%c ", _gSHexCharTbl[iCh] );
			}
			printf("\n");
		}

		j = lBuf % _STRACE_DUMP_DELIM;
		for(k=0; k<j; k++){
			iCh = *(pBuf + (i * _STRACE_DUMP_DELIM) + k);
			printf("%02x ",  iCh);
		}
		printf("\t");
		for(k=0; k<j; k++){
			iCh = *(pBuf + (i * _STRACE_DUMP_DELIM) + k);
			printf("%c ", _gSHexCharTbl[iCh] );
		}
		printf("\n");
		
	}		
	return;
}


void 	SCallStk_Dump(_t_sys_call_cookie * pCookie)
{
	int 					i;
	_t_sys_call_stack * 	pStack;
	
	if(pCookie){
		pStack = pCookie->stack;
		for(i=0; i<pCookie->lvl; i++, pStack++){
			STrace_PrintfEx("<%02d>[%-5d] %s\n", i, pStack->line, pStack->func);
		}
	}

	return;
}

